import hashlib
import random
import re

import jwt
import qiniu
import requests
from django.utils import timezone
from jwt import InvalidTokenError
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.throttling import UserRateThrottle

from education.models import Course
# from my_education import app
from my_education.settings import SECRET_KEY


class CustomizedThrottle(UserRateThrottle):
    scope = 'custom'

    def get_ident(self, request):
        token = request.META.get('HTTP_TOKEN')
        if token:
            try:
                payload = jwt.decode(token, SECRET_KEY)
                return f'user:{payload["userid"]}'
            except InvalidTokenError:
                pass
        return super().get_ident(request)

    def get_cache_key(self, request, view):
        ident = self.get_ident(request)

        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }


class LoginRequiredAuthentication(BaseAuthentication):

    def authenticate(self, request):
        # 从HTTP请求头获取token参数（用户身份令牌）
        token = request.META.get('HTTP_TOKEN')
        if token:
            try:
                # 用PyJWT中的decode函数验证令牌，验证通过会返回字典（载荷）
                payload = jwt.decode(token, SECRET_KEY)
                user = User()
                user.no = payload['userid']
                user.is_authenticated = True
                # 认证通过返回由用户和令牌构成的二元组，用户会跟request.user属性绑定
                return user, token
            except InvalidTokenError:
                raise AuthenticationFailed('请重新登录')
        raise AuthenticationFailed('请先登录')


ALL_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'


def random_captcha_code(length=4):
    return ''.join(random.choices(ALL_CHARS, k=length))


def to_md5_hex(content):
    return hashlib.md5(content.encode()).hexdigest()


def random_mobile_code(length=6):
    return ''.join(random.choices('0123456789', k=length))


@app.task
def send_message_by_sms(*, tel, message):
    resp = requests.post(
        url='http://sms-api.luosimao.com/v1/send.json',
        auth=('api', 'key-a191efa9e007373daf2c838a98533405'),
        data={
            'mobile': tel,
            'message': message
        }, timeout=3, verify=False)
    return resp.json()


@app.task
def update_last_visit(user):
    user.last_visit = timezone.now()
    user.save()


USERNAME_PATTERN = re.compile(r'[0-9a-zA-Z_]{6,20}')
TEL_PATTERN = re.compile(r'1[3-9]\d{9}')


def check_username(username):
    """检查用户名"""
    return USERNAME_PATTERN.fullmatch(username) is not None


def check_password(password):
    """检查密码"""
    return len(password) >= 8


def check_tel(tel):
    """检查手机号"""
    return TEL_PATTERN.fullmatch(tel) is not None
